{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "fbefc0bd-731b-43e4-b271-6cb4cba5c256",
   "metadata": {},
   "source": [
    "```\n",
    "Licensed to the Apache Software Foundation (ASF) under one\n",
    "or more contributor license agreements.  See the NOTICE file\n",
    "distributed with this work for additional information\n",
    "regarding copyright ownership.  The ASF licenses this file\n",
    "to you under the Apache License, Version 2.0 (the\n",
    "\"License\"); you may not use this file except in compliance\n",
    "with the License.  You may obtain a copy of the License at\n",
    "  http://www.apache.org/licenses/LICENSE-2.0\n",
    "Unless required by applicable law or agreed to in writing,\n",
    "software distributed under the License is distributed on an\n",
    "\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n",
    "KIND, either express or implied.  See the License for the\n",
    "specific language governing permissions and limitations\n",
    "under the License.\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b443d3d3-1667-4770-b57c-7f79a3ea5d42",
   "metadata": {},
   "source": [
    "## Import Sedona"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "328d0b74-1efd-468c-bc96-a469965df60b",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from sedona.spark import *\n",
    "from IPython.display import display, HTML"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f28c8117-069c-431c-ac58-6ff258b1196d",
   "metadata": {},
   "source": [
    "## Create a Sedona Context object.\n",
    "If you already have a spark instance available, simply use ```SedonaContext.create(spark)```."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e3495923-7fb4-4a6e-b62e-a4eeb9c2b306",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      ":: loading settings :: url = jar:file:/opt/spark/jars/ivy-2.5.1.jar!/org/apache/ivy/core/settings/ivysettings.xml\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Ivy Default Cache set to: /root/.ivy2/cache\n",
      "The jars for the packages stored in: /root/.ivy2/jars\n",
      "uk.co.gresearch.spark#spark-extension_2.12 added as a dependency\n",
      ":: resolving dependencies :: org.apache.spark#spark-submit-parent-d2019c7a-1755-472f-a457-e06fec742f8b;1.0\n",
      "\tconfs: [default]\n",
      "\tfound uk.co.gresearch.spark#spark-extension_2.12;2.11.0-3.4 in central\n",
      "\tfound com.github.scopt#scopt_2.12;4.1.0 in central\n",
      ":: resolution report :: resolve 68ms :: artifacts dl 3ms\n",
      "\t:: modules in use:\n",
      "\tcom.github.scopt#scopt_2.12;4.1.0 from central in [default]\n",
      "\tuk.co.gresearch.spark#spark-extension_2.12;2.11.0-3.4 from central in [default]\n",
      "\t---------------------------------------------------------------------\n",
      "\t|                  |            modules            ||   artifacts   |\n",
      "\t|       conf       | number| search|dwnlded|evicted|| number|dwnlded|\n",
      "\t---------------------------------------------------------------------\n",
      "\t|      default     |   2   |   0   |   0   |   0   ||   2   |   0   |\n",
      "\t---------------------------------------------------------------------\n",
      ":: retrieving :: org.apache.spark#spark-submit-parent-d2019c7a-1755-472f-a457-e06fec742f8b\n",
      "\tconfs: [default]\n",
      "\t0 artifacts copied, 2 already retrieved (0kB/3ms)\n",
      "25/03/19 07:22:49 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable\n",
      "Setting default log level to \"WARN\".\n",
      "To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).\n",
      "25/03/19 07:22:53 WARN UDTRegistration: Cannot register UDT for org.geotools.coverage.grid.GridCoverage2D, which is already registered.\n",
      "25/03/19 07:22:53 WARN SimpleFunctionRegistry: The function rs_union_aggr replaced a previously registered function.\n",
      "25/03/19 07:22:53 WARN UDTRegistration: Cannot register UDT for org.locationtech.jts.geom.Geometry, which is already registered.\n",
      "25/03/19 07:22:53 WARN UDTRegistration: Cannot register UDT for org.apache.sedona.common.geometryObjects.Geography, which is already registered.\n",
      "25/03/19 07:22:53 WARN UDTRegistration: Cannot register UDT for org.locationtech.jts.index.SpatialIndex, which is already registered.\n",
      "25/03/19 07:22:53 WARN SimpleFunctionRegistry: The function st_envelope_aggr replaced a previously registered function.\n",
      "25/03/19 07:22:53 WARN SimpleFunctionRegistry: The function st_intersection_aggr replaced a previously registered function.\n",
      "25/03/19 07:22:53 WARN SimpleFunctionRegistry: The function st_union_aggr replaced a previously registered function.\n"
     ]
    }
   ],
   "source": [
    "config = (\n",
    "    SedonaContext.builder()\n",
    "    .config(\n",
    "        \"spark.jars.packages\",\n",
    "        \"uk.co.gresearch.spark:spark-extension_2.13:2.14.2-4.0\",\n",
    "    )\n",
    "    .master(\"spark://localhost:7077\")\n",
    "    .getOrCreate()\n",
    ")\n",
    "\n",
    "sedona = SedonaContext.create(config)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "91d4e6ae-eeb6-46ca-89fd-8f82e6056924",
   "metadata": {},
   "source": [
    "## Read GeoTiff files"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "58c05200-27f7-46ce-b2c5-4c1dc058c96e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+--------------------+-------------------+------+--------------------+\n",
      "|                path|   modificationTime|length|             content|\n",
      "+--------------------+-------------------+------+--------------------+\n",
      "|file:/opt/workspa...|2025-02-25 23:08:24|209199|[4D 4D 00 2A 00 0...|\n",
      "+--------------------+-------------------+------+--------------------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "geotiff_df = sedona.read.format(\"binaryFile\").load(\"data/raster/test5.tiff\")\n",
    "geotiff_df.show(2)\n",
    "geotiff_df.createOrReplaceTempView(\"binary_raster\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db66242c-d0b3-4348-b2ef-4344d266cb4c",
   "metadata": {},
   "source": [
    "## Create raster columns from the read binary data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "36eb9e36-cbcb-472a-96c6-79d49305cf66",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[Stage 4:>                                                          (0 + 1) / 1]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+--------------------+\n",
      "|              raster|\n",
      "+--------------------+\n",
      "|GridCoverage2D[\"g...|\n",
      "+--------------------+\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                "
     ]
    }
   ],
   "source": [
    "raster_df = sedona.sql(\"SELECT RS_FromGeoTiff(content) as raster from binary_raster\")\n",
    "raster_df.show(2)\n",
    "raster_df.createOrReplaceTempView(\"raster_table\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3932eb9e-aeb6-4abe-a986-f26a11eb1fe3",
   "metadata": {},
   "source": [
    "## Operate on rasters using Sedona\n",
    "Once a raster column is created, you're now free to use the entire catalog of Sedona's [raster functions](https://sedona.apache.org/1.5.0/api/sql/Raster-operators/). The following part of notebook contains a few examples."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1b47699e-8ce4-4859-ace9-d12ea1f4d0b9",
   "metadata": {},
   "source": [
    "### Access raster metadata\n",
    "[RS_MetaData](https://sedona.apache.org/1.5.0/api/sql/Raster-operators/#rs_metadata) can be used to view the loaded raster's metadata (orientation and georeferencing attributes)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "6d635263-9e8b-4f74-9b91-d360d196b966",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Row(upperLeftX=-180.0, upperLeftY=90.0, gridWidth=1440, gridHeight=720, scaleX=0.25, scaleY=-0.25, skewX=0.0, skewY=0.0, srid=4326, numSampleDimensions=1, tileWidth=256, tileHeight=256)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "raster_metadata = sedona.sql(\"SELECT RS_MetaData(raster) as metadata from raster_table\")\n",
    "metadata = raster_metadata.first()[0]\n",
    "raster_srid = metadata[8]\n",
    "metadata"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "713bc8db-3143-4a79-abb5-08ad81f9393a",
   "metadata": {},
   "source": [
    "### Visualize rasters\n",
    "Sedona 1.5.0 provides [multiple ways to be able to visualize rasters](https://sedona.apache.org/1.5.0/api/sql/Raster-visualizer/). Throughout this notebook, [RS_AsImage](https://sedona.apache.org/1.5.0/api/sql/Raster-visualizer/#rs_asimage) will be used to visualize any changes to the rasters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "7fad137f-331c-4c2f-905d-dbc42cff11b6",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>rs_asimage(raster, 500)</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td><img src=\"\" width=\"500\" /></td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "SedonaUtils.display_image(raster_df.selectExpr(\"RS_AsImage(raster, 500)\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cef34e54-ac3c-48f3-836c-5a5385b79481",
   "metadata": {},
   "source": [
    "### Join based on raster predicates\n",
    "Sedona 1.5.0 now supports join predicates between raster and geometry columns.\n",
    "\n",
    "Below is a simple example that carves a small rectangle from the existing raster and attempts to join it with the original raster"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "6442349c-be2e-4609-a16e-b856745ddf46",
   "metadata": {},
   "outputs": [],
   "source": [
    "(width, height) = sedona.sql(\n",
    "    \"SELECT RS_Width(raster) as width, RS_Height(raster) as height from raster_table\"\n",
    ").first()\n",
    "(p1X, p1Y) = sedona.sql(\n",
    "    f\"SELECT RS_RasterToWorldCoordX(raster, {width / 2}, {height / 2}) \\\n",
    "                  as pX, RS_RasterToWorldCoordY(raster, {width / 2}, {height / 2}) as pY from raster_table\"\n",
    ").first()\n",
    "(p2X, p2Y) = sedona.sql(\n",
    "    f\"SELECT RS_RasterToWorldCoordX(raster, {(width / 2) + 2}, {height / 2}) \\\n",
    "                  as pX, RS_RasterToWorldCoordY(raster, {(width / 2) + 2}, {height / 2}) as pY from raster_table\"\n",
    ").first()\n",
    "(p3X, p3Y) = sedona.sql(\n",
    "    f\"SELECT RS_RasterToWorldCoordX(raster, {width / 2}, {(height / 2) + 2}) \\\n",
    "                  as pX, RS_RasterToWorldCoordY(raster, {width / 2}, {(height / 2) + 2}) as pY from raster_table\"\n",
    ").first()\n",
    "(p4X, p4Y) = sedona.sql(\n",
    "    f\"SELECT RS_RasterToWorldCoordX(raster, {(width / 2) + 2}, {(height / 2) + 2}) \\\n",
    "                  as pX, RS_RasterToWorldCoordY(raster, {(width / 2) + 2}, {(height / 2) + 2}) as pY from raster_table\"\n",
    ").first()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "ed399ee8-42b7-488b-8141-320c2bf6d9c3",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "geom_wkt = f\"SRID={int(raster_srid)};POLYGON (({p1X} {p1Y}, {p2X} {p2Y}, {p3X} {p3Y}, {p4X} {p4Y}, {p1X} {p1Y}))\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "cb8aa25f-4706-4ee7-9994-3da474c3eb2c",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "geom_df = sedona.sql(f\"SELECT ST_GeomFromEWKT('{geom_wkt}') as geom\")\n",
    "geom_df.createOrReplaceTempView(\"geom_table\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6461c14c-d479-4c64-8f8f-8c21903dedf5",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+--------------------+\n",
      "|                geom|\n",
      "+--------------------+\n",
      "|POLYGON ((-0.25 0...|\n",
      "+--------------------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "joined_df = sedona.sql(\n",
    "    \"SELECT g.geom from raster_table r, geom_table g where RS_Intersects(r.raster, g.geom)\"\n",
    ")\n",
    "joined_df.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9be5e7db-17e5-4bab-b7a3-8ee278374355",
   "metadata": {},
   "source": [
    "### Interoperability between raster and vector data types\n",
    "Sedona allows for conversions from raster to geometry and vice-versa. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc0bfd1c-7117-444a-8189-881da19846c9",
   "metadata": {},
   "source": [
    "### Convert a raster to vector using convex hull\n",
    "A convex hull geometry can be created out of a raster using [RS_ConvexHull](https://sedona.apache.org/1.5.0/api/sql/Raster-operators/#rs_convexhull)\n",
    "\n",
    "Additionally, if a raster has noDataValue specified, and you wish to tighten the convexhull to exclude noDataValue boundaries, [RS_MinConvexHull](https://sedona.apache.org/1.5.0/api/sql/Raster-operators/#rs_minconvexhull) can be used."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "22b9dd16-f720-4fa4-acb9-b80c34702a93",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+-------------------------------------------------------+\n",
      "|convex_hull                                            |\n",
      "+-------------------------------------------------------+\n",
      "|POLYGON ((-180 90, 180 90, 180 -90, -180 -90, -180 90))|\n",
      "+-------------------------------------------------------+\n",
      "\n",
      "+-------------------------------------------------------+\n",
      "|min_convex_hull                                        |\n",
      "+-------------------------------------------------------+\n",
      "|POLYGON ((-180 90, 180 90, 180 -90, -180 -90, -180 90))|\n",
      "+-------------------------------------------------------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "raster_convex_hull = sedona.sql(\n",
    "    \"SELECT RS_ConvexHull(raster) as convex_hull from raster_table\"\n",
    ")\n",
    "raster_min_convex_hull = sedona.sql(\n",
    "    \"SELECT RS_MinConvexHull(raster) as min_convex_hull from raster_table\"\n",
    ")\n",
    "raster_convex_hull.show(truncate=False)\n",
    "raster_min_convex_hull.show(truncate=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ca7e862-45c9-4559-a2e1-4e044d6b5c84",
   "metadata": {},
   "source": [
    "### Convert a geometry to raster (Rasterize a geometry)\n",
    "A geometry can be converted to a raster using [RS_AsRaster](https://sedona.apache.org/1.5.0/api/sql/Raster-writer/#rs_asraster)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "8bc32fc6-d418-4e7c-8631-57e2c623f14c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+--------------------+\n",
      "|     rasterized_geom|\n",
      "+--------------------+\n",
      "|GridCoverage2D[\"g...|\n",
      "+--------------------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "rasterized_geom_df = sedona.sql(\n",
    "    \"SELECT RS_AsRaster(ST_GeomFromWKT('POLYGON((-50 -50, 20 60, -10 100, 100 20, -50 -50))'), r.raster, 'b', false, 230) as rasterized_geom from raster_table r\"\n",
    ")\n",
    "rasterized_geom_df.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "a7eecae9-3763-405f-a22e-c7d77ff703b0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>rasterized_geom</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td><img src=\"\" width=\"250\" /></td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "SedonaUtils.display_image(\n",
    "    rasterized_geom_df.selectExpr(\"RS_AsImage(rasterized_geom, 250) as rasterized_geom\")\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "df954a81-5004-40f7-b80e-795f8569757c",
   "metadata": {},
   "source": [
    "### Perform Map Algebra operations\n",
    "Sedona provides two ways to perform [Map Algebra](https://sedona.apache.org/1.5.0/api/sql/Raster-map-algebra/) on rasters:\n",
    "1. Using RS_MapAlgebra (preferred for simpler algebraic functions)\n",
    "2. Using RS_BandAsArray and array based map algebra functions such as RS_Add, RS_Multiply (Useful for complex algebraic functions involving mutating each grid value differently.)\n",
    "\n",
    "The following example illustrates how RS_MapAlgebra can be used. \n",
    "This example uses jiffle script to invert the colors of the above illustrated rasterized geometry."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "53abef31-b1aa-42ef-8eb0-f1d9227e3893",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "raster_white_bg = rasterized_geom_df.selectExpr(\n",
    "    \"RS_MapAlgebra(rasterized_geom, NULL, 'out[0] = rast[0] == 0 ? 230 : 0;') as raster\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "75f06a1b-1ab6-478b-a50e-b621a10d6d8b",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>resampled_raster</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td><img src=\"\" width=\"250\" /></td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "SedonaUtils.display_image(\n",
    "    raster_white_bg.selectExpr(\"RS_AsImage(raster, 250) as resampled_raster\")\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fde725ec-2941-4b6e-9b52-5fd35cea6c01",
   "metadata": {},
   "source": [
    "### Resample a raster.\n",
    "Sedona 1.5.0 supports resampling a raster to different height/width or scale. It also supports changing the pivot of the raster.\n",
    "\n",
    "Refer to [RS_Resample](https://sedona.apache.org/1.5.0/api/sql/Raster-operators/#rs_resample) documentation for more details.\n",
    "\n",
    "This simple example changes the resolution of the loaded raster to 1000*1000"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "c8fdb8c7-52d5-49fa-83f2-44a9438bd509",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "resampled_raster_df = sedona.sql(\n",
    "    \"SELECT RS_Resample(raster, 1000, 1000, false, 'NearestNeighbor') as resampled_raster from raster_table\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "b14820dc-ed04-41cd-9220-73a5179f52df",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>resampled_raster</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td><img src=\"\" width=\"500\" /></td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "SedonaUtils.display_image(\n",
    "    resampled_raster_df.selectExpr(\n",
    "        \"RS_AsImage(resampled_raster, 500) as resampled_raster\"\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "bee36339-d0c1-469d-9354-980a23f24401",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+--------------------------------------------------------------------+\n",
      "|resampled_raster_metadata                                           |\n",
      "+--------------------------------------------------------------------+\n",
      "|{-180.0, 90.0, 1000, 1000, 0.36, -0.18, 0.0, 0.0, 4326, 1, 500, 500}|\n",
      "+--------------------------------------------------------------------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "resampled_raster_df.selectExpr(\n",
    "    \"RS_MetaData(resampled_raster) as resampled_raster_metadata\"\n",
    ").show(truncate=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "2b0aa64e-4a02-4c85-9ba5-6459d2002f8a",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Load another raster for some more examples\n",
    "elevation_raster_df = sedona.read.format(\"binaryFile\").load(\"data/raster/test1.tiff\")\n",
    "elevation_raster_df.createOrReplaceTempView(\"elevation_raster_binary\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "623123ac-98bc-4d51-828d-9d874cc6f471",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "elevation_raster_df = sedona.sql(\n",
    "    \"SELECT RS_FromGeoTiff(content) as raster from elevation_raster_binary\"\n",
    ")\n",
    "elevation_raster_df.createOrReplaceTempView(\"elevation_raster\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2a6afdf3-e774-432f-96a3-96a4ca8249c7",
   "metadata": {},
   "source": [
    "### Access individual values from rasters\n",
    "Sedona provides [RS_Value](https://sedona.apache.org/1.5.0/api/sql/Raster-operators/#rs_value) and [RS_Values](https://sedona.apache.org/1.5.0/api/sql/Raster-operators/#rs_values) that allow accessing raster values at given geometrical point(s).\n",
    "\n",
    "The following example extracts raster values at specific geographical points."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "ffe589e1-50b7-431a-ba84-b2c297b77f65",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+--------------+\n",
      "| raster_values|\n",
      "+--------------+\n",
      "|[115.0, 148.0]|\n",
      "+--------------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "point_wkt_1 = \"SRID=3857;POINT (-13095600.809482181 4021100.7487925636)\"\n",
    "point_wkt_2 = \"SRID=3857;POINT (-13095500.809482181 4021000.7487925636)\"\n",
    "point_df = sedona.sql(\n",
    "    \"SELECT ST_GeomFromEWKT('{}') as point_1, ST_GeomFromEWKT('{}') as point_2\".format(\n",
    "        point_wkt_1, point_wkt_2\n",
    "    )\n",
    ")\n",
    "point_df.createOrReplaceTempView(\"point_table\")\n",
    "test_df = sedona.sql(\n",
    "    \"SELECT RS_Values(raster, Array(point_1, point_2)) as raster_values from elevation_raster, point_table\"\n",
    ")\n",
    "test_df.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8643ed69-9128-49a9-80e7-f9115694695f",
   "metadata": {},
   "source": [
    "### Extract individual bands from rasters\n",
    "[RS_BandAsArray](https://sedona.apache.org/1.5.0/api/sql/Raster-operators/#rs_bandasarray) can be used to extract entire band values from a given raster"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "48f56157-ab07-456e-83fe-75d23f5bb28e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[123.0, 107.0, 156.0, 173.0, 115.0, 82.0, 165.0, 222.0, 115.0, 82.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n"
     ]
    }
   ],
   "source": [
    "band = elevation_raster_df.selectExpr(\"RS_BandAsArray(raster, 1)\").first()[0]\n",
    "print(\n",
    "    band[500:520],\n",
    ")  # Print a part of a band as an array horizontally"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e586b0e5-935a-47fa-8ebf-b63ddd9a48a8",
   "metadata": {},
   "source": [
    "### Visualize Raster MBRs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "2a2c7086-9588-48a7-a710-c10b8c5e4875",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Convert raster to its convex hull and transform it to EPSG:4326 to be able to visualize\n",
    "raster_mbr_df = elevation_raster_df.selectExpr(\n",
    "    \"ST_Transform(RS_ConvexHull(raster), 'EPSG:3857', 'EPSG:4326') as raster_mbr\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "6f39b3db-a0b1-4842-a5ca-b5a5850f3ea7",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "User Guide: https://docs.kepler.gl/docs/keplergl-jupyter\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "40e21039219c43fd860cb2a0dba17475",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "KeplerGl(data={'RasterMBR': {'index': [0], 'columns': ['geometry'], 'data': [['POLYGON ((-117.6417329630247508…"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sedona_kepler_map_elevation = SedonaKepler.create_map(\n",
    "    df=raster_mbr_df, name=\"RasterMBR\"\n",
    ")\n",
    "sedona_kepler_map_elevation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0a684add-0608-41cb-afc6-230d15b3a97b",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
